﻿using MelodysDemo.Application.Lists;
using Microsoft.EntityFrameworkCore;
using QRCoder;
using System.Drawing;
using System.Net;

namespace MelodysDemo.API.Controllers
{
    [ApiController]
    [Route("[controller]/[action]")]
    public class AnswersController : Controller
    {
        readonly IRepository<SurveyClazzQuestionnaire, int> _clazzQuestionnaire;//班级问卷信息表
        readonly IRepository<SurveyQuestionnaire, int> _questtionnaies;//问卷
        readonly IRepository<SurveyQuestion, int> _questtion;//问题
        readonly IRepository<SurveyOption, int> _option;//选项
        readonly IRepository<SurveyAnswer, int> _answer;//答题记录表
        readonly IRepository<SurveyAnswerDetail, int> _answerDetail;//答题详情记录表
        readonly IRepository<SurveyClazz, int> _clazz;//班级
        readonly IHttpContextAccessor _httpContext;//Http配置
        public AnswersController(IRepository<SurveyClazzQuestionnaire, int> clazzQuestionnaire,
                                             IRepository<SurveyQuestionnaire, int> questtionnaies,
                                             IRepository<SurveyQuestion, int> questtion,
                                             IRepository<SurveyOption, int> option,
                                             IRepository<SurveyAnswer, int> answer,
                                             IRepository<SurveyAnswerDetail, int> answerDetail,
                                             IRepository<SurveyClazz, int> clazz,
                                             IHttpContextAccessor httpContext)
        {
            _clazzQuestionnaire = clazzQuestionnaire;
            _questtionnaies = questtionnaies;
            _questtion = questtion;
            _option = option;
            _answer = answer;
            _answerDetail = answerDetail;
            _clazz = clazz;
            _httpContext = httpContext;
        }
        //答题
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> AnswersAdd([FromBody] AnswerAddInput input)
        {
            //1.查出对应班级问卷信息
            SurveyClazzQuestionnaire cqn = await _clazzQuestionnaire
                                           .FirstOrDefaultAsync(x => x.Id == input.ClazzQuestionnaireId);
            string sip = null;
            if (input.SourceIp is { Length: > 0 })
                sip = input.SourceIp;
            else
                sip = ToGetIP.GetUserIP();
            //判断该问卷是否开启IP限制（1：是，0：否）
            if (cqn.IsIpLimit == 1)
            {
                //判断是否存在
                SurveyAnswer anr = await _answer
                                 .FirstOrDefaultAsync(a => a.ClazzQuestionnaireId == cqn.Id
                                 && a.SourceIp.Equals(sip));
                if (anr != null)
                {
                    return Json(new UIResult(-1, "该IP已完成问卷"));
                }
            }          
            //2.创建 SurveyAnswer 表的集合
            SurveyAnswer answer = new SurveyAnswer
            {
                CostTime = input.timeCounter,//答题时间
                Score = 0,//默认为0
                ClazzId = cqn.ClazzId,//班级Id
                QuestionnaireId = cqn.QuestionnaireId,//问卷Id
                ClazzQuestionnaireId = cqn.Id,//教学评价Id
                SourceType = input.SourceType,//来源类型(1：mobile，2：pc)
                SourceIp = sip,//来源IP
                SourceLocation = input.SourceLocation,//来源IP地址
                SourceDetail = input.SourceDetail,//来源详情
                Status = 1,//正常
                Version = 0,//版本号
                Creator = "lhb",
                CreateTime = DateTime.Now,
                Modifier = "lhb",
                ModifiedTime = DateTime.Now,
                IsDelete = 0
            };
            await _answer.InsertAsync(answer);
            //3.根据选项组查出对应的选项
            byte score = 0;//默认总分是0
            foreach (int id in input.selectedOptions)
            {
                //查询单条选项
                var o = await _option.FirstOrDefaultAsync(x => x.Id == id);
                score += o.Score;//获取每个选项的分数
                SurveyAnswerDetail answerDetail = new SurveyAnswerDetail
                {
                    AnswerId = answer.Id,//答题记录Id
                    QuestionId = o.QuestionId,//问题Id
                    OptionId = o.Id,//选项Id
                    OptionSn = o.Sn,//选项编号
                    Version = 0,//版本号
                    Creator = answer.Creator,
                    CreateTime = DateTime.Now,
                    Modifier = answer.Modifier,
                    ModifiedTime = DateTime.Now,
                    IsDelete = 0
                };
                await _answerDetail.InsertAsync(answerDetail);
            }
            //4.修改当前答题记录的总分
            SurveyAnswer obj = await _answer.FirstOrDefaultAsync(x => x.Id == answer.Id);
            obj.Score = score;//修改总分
            SurveyAnswer r = await _answer.UpdateAsync(obj);
            if (r != null)
            {
                return Json(new UIResult(0, "答题成功"));
            }
            return Json(new UIResult(-1, "答题失败"));
        }

        //获取IP
        [HttpGet]
        [AllowAnonymous]
        public IActionResult GetUserIP()
        {
            string hostName = Dns.GetHostName();
            IPAddress[] addresses = Dns.GetHostAddresses(hostName);
            foreach (IPAddress address in addresses)
            {
                if (address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork) // IPv4
                {
                    //返回当前连接的网络的IP地址
                    return Json(new { code = 0, userIP = address.ToString() });

                }
            }
            return Json(new UIResult(-1, "请求失败"));
        }

        //生成二维码
        [HttpGet]
        public IActionResult GenerateQRCode([FromQuery] string title)
        {
            //创建一个新的QRCodeGenerator实例
            QRCodeGenerator qrGenerator = new QRCodeGenerator();
            //创建一个二维码 url 为内容
            QRCodeData qrCodeData = qrGenerator.CreateQrCode(title, QRCodeGenerator.ECCLevel.M, true);
            var qrcode = new BitmapByteQRCode(qrCodeData);
            var bitmap = qrcode.GetGraphic(10);

            //创建唯一的文件名
            string fileName = Guid.NewGuid().ToString("N") + ".png";
            string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), fileName);

            // 将位图保存到文件
            using (FileStream fs = new FileStream(filePath, FileMode.Create))
            {
                fs.Write(bitmap, 0, bitmap.Length);
            }

            //将文件内容读取为字节数组
            byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);

            //将字节数组转换为Base64格式的字符串
            string base64String = Convert.ToBase64String(fileBytes);

            //返回Base64格式的字符串
            return Json(new UIResult(0, "生成成功", base64String));
            //return File(System.IO.File.ReadAllBytes(filePath), "QRimage/png", fileName);
        }

        //答题分析
        [HttpGet]
        public async Task<IActionResult> AnswersAnay([FromQuery] long id)
        {
            //通过 ClazzQuestionnaireId 获取 Answers 表中有效的数据
            var aslist = _answer.GetAll()
                                           .Where(x => x.ClazzQuestionnaireId == id&&x.Status==1).ToList();
            //获取答题详情表的数据所属 Answers 表的数据
            List<SurveyAnswerDetail> sdList = new List<SurveyAnswerDetail>();
            foreach (SurveyAnswer ass in aslist)
            {
                var sd = _answerDetail.GetAll()
                                                .Include(x => x.Option)
                                                .Include(x => x.Question)
                                                .Where(x => x.AnswerId == ass.Id);
                sdList.AddRange(sd);
            }
            //获取有效问卷数量、平均时间、平均评分
            AnswerAnayDto ansAnay=new AnswerAnayDto();
            ansAnay.Count =aslist.Count;//数量
            //平均时间和平均分
            ansAnay.AvgTimes = 0;
            ansAnay.AvgScores = 0;
            foreach (SurveyAnswer ass in aslist)
            {
                var answer = await _answer.FirstOrDefaultAsync(a => a.Id == ass.Id);
                ansAnay.AvgTimes += answer.Score;
                ansAnay.AvgScores += answer.CostTime;
            }
            ansAnay.AvgTimes /= aslist.Count;
            ansAnay.AvgScores /= aslist.Count;
            //按问题的Id分组
            var optList = sdList.OrderBy(x => x.Question.Sn)
                                                      .GroupBy(x => new { x.QuestionId, x.Question.Title,x.Question.Sn })
                                                      .Select(x => new AnswerDto
                                                      {
                                                          Id = x.Key.Sn,//问题序号
                                                          Title = x.Key.Title,//问题题干
                                                          AvgScore = x.Average(x => x.Option.Score),//平均分
                                                          ScoreDList = sdList.Where(ad => ad.QuestionId == x.Key.QuestionId)
                                                                   .GroupBy(x => new { x.Option.Score })
                                                                   .Select(x => new ScoreDto
                                                                   {
                                                                       count = x.Count(),
                                                                       Score = x.Key.Score
                                                                   }).ToList()//给每个问题的所有选项赋值
                                                      }).ToList();

            return Json(new { code = 0, data = optList, ansAnay= ansAnay });
        }

        //答题列表
        [HttpGet]
        public async Task<IActionResult> AnswersList([FromQuery] long id)
        {
            //根据班级评价Id查询对应的班级名、问卷名和填写人数
            SurveyClazzQuestionnaire? cqn = await _clazzQuestionnaire
                                         .FirstOrDefaultAsync(x => x.Id == id);
            //查询对应的班级和问卷
            SurveyClazz? clazz = await _clazz
                                 .FirstOrDefaultAsync(c => c.Id == cqn.ClazzId);
            SurveyQuestionnaire? qnaire = await _questtionnaies
                                        .FirstOrDefaultAsync(x => x.Id == cqn.QuestionnaireId);
            //查询对应的答题记录
            List<SurveyAnswer>? answer = await _answer.GetAll()
                                        .Where(a => a.ClazzQuestionnaireId == cqn.Id)
                                        .AsNoTracking().ToListAsync();
            //人数
            int count = answer.Count();
            if (answer != null)
                return Json(new { code = 0, msg = "请求成功", count = count, data = answer, clazz = clazz, qnaire = qnaire });
            return Json(new UIResult(-1, "数据请求异常"));
        }

        //答题详情
        [HttpGet]
        public async Task<IActionResult> AnswerDetails([FromQuery] long id)
        {
            //根据答题记录Id查询对应的详情
            SurveyAnswer? ans = await _answer
                                .FirstOrDefaultAsync(a => a.Id == id);
            //查询问卷
            SurveyQuestionnaire? qnaire = await _questtionnaies
                                        .FirstOrDefaultAsync(x => x.Id == ans.QuestionnaireId);
            //查询答题详情
            List<AnswerDetailDto>? list = _answerDetail.GetAll()
                                                .Include(x => x.Question)
                                                .Include(x => x.Option)
                                                .Where(x => x.AnswerId == ans.Id)
                                                .Select(a => new AnswerDetailDto
                                                {
                                                    Sn = a.Question.Sn,//编号
                                                    Title = a.Question.Title,//题干
                                                    Content = a.Option.Content,//选项
                                                    Score = a.Option.Score//得分
                                                }).AsNoTracking().ToList();
            if (list != null)
                return Json(new { code = 0, msg = "请求成功", data = list, qnaire = qnaire, answer = ans });
            return Json(new UIResult(-1, "数据请求异常"));
        }

        //无效
        //0:无效
        [HttpPatch]
        public async Task<IActionResult> AnswersOff([FromBody] List<int> ids)
        {
            string uname = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
            foreach (int id in ids)
            {
                var an = await _answer.FirstOrDefaultAsync(x => x.Id == id);
                if (an != null)
                {
                    an.Status = 0;//无效
                    an.Modifier = uname;
                    an.ModifiedTime= DateTime.Now;
                    an.Version++;
                    await _answer.UpdateAsync(an);
                }
            }
            return Json(new UIResult(0, "已设置无效"));
        }

        //1:正常
        [HttpPatch]
        public async Task<IActionResult> AnswersNo([FromBody] List<int> ids)
        {
            string uname = HttpContext.User.Claims.First(c => c.Type == ClaimTypes.Name).Value;
            foreach (int id in ids)
            {
                var an = await _answer.FirstOrDefaultAsync(x => x.Id == id);
                if (an != null)
                {
                    an.Status = 1;//正常
                    an.Modifier = uname;
                    an.ModifiedTime = DateTime.Now;
                    an.Version++;
                    await _answer.UpdateAsync(an);
                }
            }
            return Json(new UIResult(0, "已恢复正常"));
        }

    }
}
